Computer systems contain a finite number of memory locations. These locations may be dedicated to the temporary storage of data or software applications, i.e., programs, or may be dynamically allocated to the programs as they operate to hold data required or produced by a program during execution. A program which analyzes data obtained from a data base, for example, utilizes memory locations temporarily to hold the data retrieved from the data base and also to hold the results of the analysis. These memory locations are required only during the execution of the program, and are thus allocated dynamically as needed, so that they remain otherwise available.
When the program completes its manipulation of various data from the data base, the program can then deallocate, or release, the dynamically allocated memory locations used to hold this data. This frees the locations for other uses and/or for re-use by the same program. Similarly, if various results of the data manipulation are no longer needed, the program can release the memory locations used to store the results. Such allocations and releases may occur many times throughout the execution of the program.
To allocate and release memory locations, the programs invoke memory allocation and deallocation routines, which are low-level operating system routines, commonly referred to as "service routines," that control the actual allocation and release of the system memory locations. There are various types of memory allocation/deallocation routines directed to particular arrangements of memory locations. One such routine directs the allocation of memory locations as various sizes of blocks, i.e., predetermined numbers of proximate memory locations. Various other routines direct the allocation of memory locations as pages i.e., locations with the same higher order addresses, and so forth. A program which calls for the allocation of unnecessarily large blocks of memory, particularly large contiguous blocks, may interfere with the operation of other programs that are running simultaneously on the system. Alternatively, programs which call for the allocation of memory in blocks that are too small may interfere with their own operations.
A user may not be aware of a problem with memory allocation. A program may run inexplicably slowly, for example, when memory is allocated in blocks which are too small. Such a program must invoke the memory allocation routines more often than would be required if larger blocks of memory were requested by the program. Each invocation takes time, and thus, the program is delayed but otherwise operates as expected. Another problem which is not readily detected is that of memory fragmentation, which, for example, increases the time required to access a table stored in non-contiguous memory locations. The user can not appropriately modify the program to avoid these delays and time-consuming access operations, unless he or she learns of the problems.
Programs which invoke memory allocation routines should also invoke deallocation routines, to release the allocated memory locations. Otherwise, the memory locations remain unavailable for other uses, even repeated uses by the same program. If, for example, a program sub-routine which calls a memory allocation routine, but not an associated memory deallocation routine, is invoked repeatedly to calculate intermediate values, the sub-routine calls for new memory locations at each invocation and retains those previously allocated. Accordingly, the program sub-routine acquires more and more locations, and prevents other sub-routines from using these locations.
Determining when, or if, memory locations are to be released by various routines is often a problem in a large and/or complex program, even if the program is highly structured. For example, the call to the memory deallocation routine may be part of the program sub-routine which includes the call to the allocation routine, or it may be part of any number of related program sub-routines which utilize that sub-routine. Tracing these commands through the various sub-routines can be a difficult task.
The memory deallocation routines must be of the same type as the associated allocation routines. Otherwise, the deallocation routines do not release the locations. Memory locations allocated in pages or in blocks, for example, must be released in pages or in blocks of the same size. Accordingly, a user may include in a sub-routine a call to the wrong deallocation routine and be unaware of the ineffectiveness of this routine.
Memory analyzers that indicate to a user the status of the respective memory locations, i.e., whether the locations are free or allocated, have recently become available. While these memory analyzers, such as Heap View, marketed by Silicon Graphics Incorporated, provide an overview of dynamic memory allocation, they do not provide enough information to enable a user to analyze whether a program, or more specifically a program sub-routine and/or related sub-routines, appropriately allocate and/or release memory locations. In particular, the Heap View analyzer requires that a user define "intervals." It then points out "errors" in the intervals, such as unreleased memory locations or "bad" releases, which are releases of memory locations that either have not been allocated or have been previously released. If a release occurs in a different interval from that of the associated allocation, the Heap View analyzer mistakenly points to the release as an error. Also, the analyzer will not necessarily reveal a situation in which memory is allocated in blocks that are either too large or too small. Thus, it does not always provide sufficient information to determine when actual errors occur or when memory is used inefficiently.